# -*- coding: utf-8 -*-
import sys
import os
import os.path as osp
from copy import deepcopy
import time
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget

from qtpy import QtCore
from qtpy.QtCore import Qt, QRect
from qtpy import QtGui
from qtpy import QtWidgets

from returnlabels import __appname__

from .utils import DebugButton
from .utils import PoolButton
from .utils import ParkingSlotReturnLabels
from .utils import Freespace2dReturnLabels
from .utils import Lidar3dReturnLabels
from .utils import RoadMarkerArrowReturnLabels
from .utils import FisheyeMonoReturnLabels
from .utils import SignKeypoint2DReturnLabels


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, 
                 headers=None, 
                 url_dict=None, 
                 project_dict=None, 
                 ):
        super(MainWindow, self).__init__()
        self.setWindowTitle(__appname__)
        self.setMinimumSize(720, 480)

        self.headers = headers
        self.url_dict = url_dict
        self.project_dict = project_dict

        self.repair_batch_name = None
        self.url_status = "return"
        self.url = self.url_dict[self.url_status]
        self.current_project = "Parking Slot"
        self.project_info = self.project_dict[self.current_project]

        self.origin_dir = None
        self.input_dir = None
        self.output_dir = None
        self.debug = False
        self.muti_pool = False

        if self.current_project in self.project_dict:
            for project_name, project_version in self.project_info.items():
                self.project_name = project_name
                self.project_version = project_version
        
        # --------------------------------- repair_batch ---------------------------------
        self.repair_batch_label = QtWidgets.QLabel("设置返修批次名称：")
        self.set_repair_batch = QtWidgets.QPushButton("Set Repair Batch", self)
        self.set_repair_batch.clicked.connect(self.set_repair_batch_name)
        self.repair_batch_label_set = QtWidgets.QLabel()
        repair_batch_layout = QtWidgets.QHBoxLayout()
        repair_batch_layout.addWidget(self.repair_batch_label, 1)
        repair_batch_layout.addWidget(self.set_repair_batch, 2)
        repair_batch_layout.addWidget(self.repair_batch_label_set, 3)
        # ---------------------------------------------------------------------------------

        # --------------------------------- url ---------------------------------
        self.url_label = QtWidgets.QLabel("设置 URL：")
        self.set_url = QtWidgets.QComboBox(self)
        for item in self.url_dict.keys():
            self.set_url.addItem(item)
        self.set_url.currentIndexChanged.connect(self.set_rerurn_repair_url)
        self.url_label_set = QtWidgets.QLabel()
        url_layout = QtWidgets.QHBoxLayout()
        url_layout.addWidget(self.url_label, 1)
        url_layout.addWidget(self.set_url, 2)
        url_layout.addWidget(self.url_label_set, 3)
        # ------------------------------------------------------------------------

        # --------------------------------- project ---------------------------------
        self.project_label = QtWidgets.QLabel("设置项目信息：")
        self.set_project = QtWidgets.QComboBox(self)
        for item in self.project_dict.keys():
            self.set_project.addItem(item)
        self.set_project.currentIndexChanged.connect(self.set_project_info)
        self.project_label_set = QtWidgets.QLabel()
        project_layout = QtWidgets.QHBoxLayout()
        project_layout.addWidget(self.project_label, 1)
        project_layout.addWidget(self.set_project, 2)
        project_layout.addWidget(self.project_label_set, 3)
        # ----------------------------------------------------------------------------

        # --------------------------------- origin dir ---------------------------------
        self.origin_label = QtWidgets.QLabel("选择原始数据存放路径：")
        self.set_origin_data = QtWidgets.QPushButton("Set Origin Data", self)
        self.set_origin_data.clicked.connect(self.set_origin_directory)
        self.origin_label_set = QtWidgets.QLabel()
        origin_layout = QtWidgets.QHBoxLayout()
        origin_layout.addWidget(self.origin_label, 1)
        origin_layout.addWidget(self.set_origin_data, 2)
        origin_layout.addWidget(self.origin_label_set, 3)
        # ------------------------------------------------------------------------------

        # --------------------------------- input dir ---------------------------------
        self.input_label = QtWidgets.QLabel("选择待还标数据存放路径：")
        self.set_input_dir = QtWidgets.QPushButton("Set Input Dir", self)
        self.set_input_dir.clicked.connect(self.set_input_directory)
        self.input_label_set = QtWidgets.QLabel()
        input_layout = QtWidgets.QHBoxLayout()
        input_layout.addWidget(self.input_label, 1)
        input_layout.addWidget(self.set_input_dir, 2)
        input_layout.addWidget(self.input_label_set, 3)
        # -----------------------------------------------------------------------------

        # --------------------------------- output dir ---------------------------------
        self.output_label = QtWidgets.QLabel("选择还标结果存放路径：")
        self.set_output_dir = QtWidgets.QPushButton("Set Output Dir", self)
        self.set_output_dir.clicked.connect(self.set_output_directory)
        self.output_label_set = QtWidgets.QLabel()
        output_layout = QtWidgets.QHBoxLayout()
        output_layout.addWidget(self.output_label, 1)
        output_layout.addWidget(self.set_output_dir, 2)
        output_layout.addWidget(self.output_label_set, 3)
        # ------------------------------------------------------------------------------

        # --------------------------------- debug ---------------------------------
        self.debug_button = DebugButton()
        self.debug_button.set_debug_true.toggled.connect(self.set_debug)
        self.debug_button.set_debug_false.toggled.connect(self.set_debug)
        # --------------------------------------------------------------------------

        # --------------------------------- multi-pool ---------------------------------
        self.pool_button = PoolButton()
        self.pool_button.set_pool_single.toggled.connect(self.set_pool)
        self.pool_button.set_pool_multi.toggled.connect(self.set_pool)
        # --------------------------------------------------------------------------


        # --------------------------------- start ---------------------------------
        self.start_process = QtWidgets.QPushButton("开始还标", self)
        self.start_process.clicked.connect(self.start_return_labels)
        # -------------------------------------------------------------------------

        # --------------------------------- global layout ---------------------------------
        global_layout = QtWidgets.QVBoxLayout()
        global_layout.addLayout(repair_batch_layout, 1)
        global_layout.addLayout(url_layout, 1)
        global_layout.addLayout(project_layout, 1)
        global_layout.addLayout(origin_layout, 1)
        global_layout.addLayout(input_layout, 1)
        global_layout.addLayout(output_layout, 1)
        global_layout.addWidget(self.debug_button, 1)
        global_layout.addWidget(self.pool_button, 1)
        global_layout.addWidget(self.start_process, 1)
        # ----------------------------------------------------------------------------------

        # --------------------------------- mainwindow widget ---------------------------------
        widget = QtWidgets.QWidget()
        widget.setLayout(global_layout)
        self.setCentralWidget(widget)
        # -------------------------------------------------------------------------------------

    # --------------------------------- slot functions ---------------------------------
    def set_repair_batch_name(self):
        self.repair_batch_name, ok = QtWidgets.QInputDialog.getItem(self, "设置返修批次名称", "项目名称：", [])
        if ok:
            self.repair_batch_label_set.setText(f"'{self.repair_batch_name}'")
            print(f"===> Set Repair Batch Name: '{self.repair_batch_name}'")

    def set_rerurn_repair_url(self):
        self.url_status = self.set_url.currentText()
        self.url = self.url_dict[self.url_status]
        self.url_label_set.setText(f"'{self.url}'")
        print(f"===> Set URL: '{self.url}'")

    def set_project_info(self):
        self.current_project = self.set_project.currentText()
        self.project_info = self.project_dict[self.current_project]
        for project_name, project_version in self.project_info.items():
            self.project_name = project_name
            self.project_version = project_version
        self.project_label_set.setText(f"{self.project_info}")
        print(f"===> Set Project: {self.project_info}")
        print(f"===> project_name: {self.project_name}")
        print(f"===> project_version: {self.project_version}")

    def set_origin_directory(self):
        self.origin_dir = QtWidgets.QFileDialog.getExistingDirectory(None, "Please select directory", os.getcwd())
        self.origin_label_set.setText(f"'{self.origin_dir}'")
        print(f"===> Set origin directory: '{self.origin_dir}'")

    def set_input_directory(self):
        self.input_dir = QtWidgets.QFileDialog.getExistingDirectory(None, "Please select directory", os.getcwd())
        self.input_label_set.setText(f"'{self.input_dir}'")
        print(f"===> Set input directory: '{self.input_dir}'")

    def set_output_directory(self):
        self.output_dir = QtWidgets.QFileDialog.getExistingDirectory(None, "Please select directory", os.getcwd())
        self.output_label_set.setText(f"'{self.output_dir}'")
        print(f"===> Set output directory: '{self.output_dir}'")

    def set_debug(self):
        debug_status = self.debug_button.sender()
        if debug_status.text() == "True":
            if debug_status.isChecked() == True:
                self.debug = True
                print("===> Debug: True.")
        
        if debug_status.text() == "False":
            if debug_status.isChecked() == True:
                self.debug = False
                print("===> Debug: False.")

    def set_pool(self):
        pool_status = self.pool_button.sender()
        if pool_status.text() == "Single Pool":
            if pool_status.isChecked() == True:
                self.muti_pool = False
                print("===> Single Pool.")
        if pool_status.text() == "Multi Pool":
            if pool_status.isChecked() == True:
                self.muti_pool = True
                print("===> Multi Pool.")

    def start_return_labels(self):
        if self.input_dir!=None and self.output_dir!=None:
            print("===> Start Return Labels...")

            if self.current_project == "Parking Slot":
                return_label = ParkingSlotReturnLabels(
                    headers=self.headers, 
                    url=self.url,                               # 正常还标用 url_return 返修还标用 url_repair
                    label_project=self.project_name,            # 项目名称
                    label_rule_version=self.project_version,    # 项目版本
                    input_dir=self.input_dir,                   # 待还标数据路径
                    output_dir=self.output_dir,                 # 输出路径 保存上传成功数据备份和失败的数据 在 excel 表格内
                    debug=self.debug,                           # 调试
                    filter_data=osp.dirname(self.output_dir),   # 已经上传成功数据路径（需过滤掉）
                    repair_batch=self.repair_batch_name,        # 返修还标的 repair_batch 名称
                )
                start = time.time()
                if "return" in self.url_status:
                    if self.muti_pool:
                        return_label.parking_slot_return_pool()
                    else:
                        return_label.parking_slot_return()
                if "repair" in self.url_status:
                    if self.muti_pool:
                        return_label.parking_slot_repair_pool()
                    else:
                        return_label.parking_slot_repair()
                end = time.time()
                print(f"===> Running Time: {round(end-start, 2)} s")
            
            if self.current_project == "Freespace 2D":
                return_label = Freespace2dReturnLabels(
                    headers=self.headers, 
                    url=self.url,                               # 正常还标用 url_return 返修还标用 url_repair
                    label_project=self.project_name,            # 项目名称
                    label_rule_version=self.project_version,    # 项目版本
                    input_dir=self.input_dir,                   # 待还标数据路径
                    output_dir=self.output_dir,                 # 输出路径 保存上传成功数据备份和失败的数据 在 excel 表格内
                    debug=self.debug,                           # 调试
                    filter_data=osp.dirname(self.output_dir),   # 已经上传成功数据路径（需过滤掉）
                    repair_batch=self.repair_batch_name,        # 返修还标的 repair_batch 名称
                )
                start = time.time()
                if "return" in self.url_status:
                    if self.muti_pool:
                        return_label.freespace2d_return_pool()
                    else:
                        return_label.freespace2d_return()
                if "repair" in self.url_status:
                    if self.muti_pool:
                        return_label.freespace2d_repair_pool()
                    else:
                        return_label.freespace2d_repair()
                end = time.time()
                print(f"===> Running Time: {round(end-start, 2)} s")

            if self.current_project == "Ladir 3D" and self.origin_dir!=None:
                return_label = Lidar3dReturnLabels(
                    headers=self.headers, 
                    url=self.url,                               # 正常还标用 url_return 返修还标用 url_repair
                    label_project=self.project_name,            # 项目名称
                    label_rule_version=self.project_version,    # 项目版本
                    input_dir=self.input_dir,                   # 待还标数据路径
                    output_dir=self.output_dir,                 # 输出路径 保存上传成功数据备份和失败的数据 在 excel 表格内
                    debug=self.debug,                           # 调试
                    filter_data=osp.dirname(self.output_dir),   # 已经上传成功数据路径（需过滤掉）
                    repair_batch=self.repair_batch_name,        # 返修还标的 repair_batch 名称
                    origin_data=self.origin_dir                 # 原始数据
                )
                start = time.time()
                if "return" in self.url_status:
                    if self.muti_pool:
                        return_label.lidar3d_return_pool()
                    else:
                        return_label.lidar3d_return()
                if "repair" in self.url_status:
                    if self.muti_pool:
                        return_label.lidar3d_repair_pool()
                    else:
                        return_label.lidar3d_repair()
                end = time.time()
                print(f"===> Running Time: {round(end-start, 2)} s")

            if self.current_project == "Road Marker Arrow":
                return_label = RoadMarkerArrowReturnLabels(
                    headers=self.headers, 
                    url=self.url,                               # 正常还标用 url_return 返修还标用 url_repair
                    label_project=self.project_name,            # 项目名称
                    label_rule_version=self.project_version,    # 项目版本
                    input_dir=self.input_dir,                   # 待还标数据路径
                    output_dir=self.output_dir,                 # 输出路径 保存上传成功数据备份和失败的数据 在 excel 表格内
                    debug=self.debug,                           # 调试
                    filter_data=osp.dirname(self.output_dir),   # 已经上传成功数据路径（需过滤掉）
                    repair_batch=self.repair_batch_name,        # 返修还标的 repair_batch 名称
                )
                start = time.time()
                if "return" in self.url_status:
                    if self.muti_pool:
                        return_label.road_marker_arrow_return_pool()
                    else:
                        return_label.road_marker_arrow_return()
                if "repair" in self.url_status:
                    if self.muti_pool:
                        return_label.road_marker_arrow_repair_pool()
                    else:
                        return_label.road_marker_arrow_repair()
                end = time.time()
                print(f"===> Running Time: {round(end-start, 2)} s")

            if self.current_project == "Fisheye Mono" and self.origin_dir!=None:
                return_label = FisheyeMonoReturnLabels(
                    headers=self.headers, 
                    url=self.url,                               # 正常还标用 url_return 返修还标用 url_repair
                    label_project=self.project_name,            # 项目名称
                    label_rule_version=self.project_version,    # 项目版本
                    input_dir=self.input_dir,                   # 待还标数据路径
                    output_dir=self.output_dir,                 # 输出路径 保存上传成功数据备份和失败的数据 在 excel 表格内
                    debug=self.debug,                           # 调试
                    filter_data=osp.dirname(self.output_dir),   # 已经上传成功数据路径（需过滤掉）
                    repair_batch=self.repair_batch_name,        # 返修还标的 repair_batch 名称
                    origin_data=self.origin_dir                 # 原始数据
                )
                start = time.time()
                if "return" in self.url_status:
                    if self.muti_pool:
                        return_label.fisheye_mono_return_pool()
                    else:
                        return_label.fisheye_mono_return()
                if "repair" in self.url_status:
                    if self.muti_pool:
                        return_label.fisheye_mono_repair_pool()
                    else:
                        return_label.fisheye_mono_repair()
                end = time.time()
                print(f"===> Running Time: {round(end-start, 2)} s")

            if self.current_project == "Sign Keypoint 2D":
                return_label = SignKeypoint2DReturnLabels(
                    headers=self.headers, 
                    url=self.url,                               # 正常还标用 url_return 返修还标用 url_repair
                    label_project=self.project_name,            # 项目名称
                    label_rule_version=self.project_version,    # 项目版本
                    input_dir=self.input_dir,                   # 待还标数据路径
                    output_dir=self.output_dir,                 # 输出路径 保存上传成功数据备份和失败的数据 在 excel 表格内
                    debug=self.debug,                           # 调试
                    filter_data=osp.dirname(self.output_dir),   # 已经上传成功数据路径（需过滤掉）
                    repair_batch=self.repair_batch_name,        # 返修还标的 repair_batch 名称
                )
                start = time.time()
                if "return" in self.url_status:
                    if self.muti_pool:
                        return_label.sign_keypoint_2d_return_pool()
                    else:
                        return_label.sign_keypoint_2d_return()
                if "repair" in self.url_status:
                    if self.muti_pool:
                        return_label.sign_keypoint_2d_repair_pool()
                    else:
                        return_label.sign_keypoint_2d_repair()
                end = time.time()
                print(f"===> Running Time: {round(end-start, 2)} s")
    # ----------------------------------------------------------------------------------

    # --------------------------------- event functions ---------------------------------
    def closeEvent(self, event):
        a = QtWidgets.QMessageBox.question(self, '是否退出', '确定要退出吗?', 
                                           QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, 
                                           QtWidgets.QMessageBox.No)
        if a == QtWidgets.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
    # ----------------------------------------------------------------------------------
